package tech.waterism.service.controller;

import tech.waterism.modelbase.PredictResult;
import com.alibaba.fastjson.JSON;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import tech.waterism.model.LAG_3;
import tech.waterism.service.cache.ModelTaskCache;
import tech.waterism.service.service.ModelCalculationService;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
 * LAG(滞后演算)模型控制器
 * 
 * <p>提供滞后演算水文模型的REST API接口
 * 
 * @author 高宇
 * @since 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/api/model/lag")
@Tag(name = "LAG_3模型", description = "三水源滞后演算模型 - 河道汇流模拟")
public class LAGModelController {

    @Autowired
    private ModelCalculationService calculationService;

    @Autowired
    private ModelTaskCache taskCache;

    @PostMapping("/calculate")
    @Operation(
            summary = "LAG_3模型同步计算",
            description = """
                    执行三水源滞后演算模型同步计算，模拟三水源河道汇流过程。
                    
                    **适用场景：** 小规模计算（<500时段）、实时性要求高
                    
                    ## 输入参数说明
                    
                    ### 模型参数
                    - `LAG`: 滞时 (时段) - 范围: 1-10
                    - `KK`: 河道演算系数 - 范围: 0.3-0.8
                    - `CS`: 河道消退系数 - 范围: 0-1
                    - `CI`: 壤中流消退系数 - 范围: 0-1
                    - `CG`: 地下水消退系数 - 范围: 0-1
                    - `X`: 马斯京根权重系数 - 范围: 0-0.5
                    - `MP`: 河段数量
                    - `F`: 流域面积 (km²)
                    - `clen`: 时段长度 (h)
                    
                    ### 时序输入
                    - `flowSeries`: 流量时间序列（包含time, rain, runoff, sources）
                    或
                    - `dt`: 时间序列, `rSim`: 三水源产流序列 [[RS], [RI], [RG]]
                    
                    ### 初始状态
                    - `QSIG`: 初始河道流量序列
                    - `QXSIG`: 初始河段流量
                    - `QSP`, `QIP`, `QGP`: 初始三水源流量
                    
                    ## 输出结果
                    - `qSim`: 河道流量过程线 (m³/s)
                    - `rSim`: 三水源径流分量 [[RS], [RI], [RG]]
                    - `newStatus`: 各时段状态信息
                    
                    ## 算法说明
                    采用马斯京根法 + 滞后演算法：
                    1. 三水源分别消退演算
                    2. 汇总后进行河道滞后演算
                    3. 马斯京根河道演进
                    """
    )
    public ResponseEntity<?> calculate(@RequestBody Map<String, Object> inputData) {
        try {
            log.info("收到LAG_3模型同步计算请求");
            log.debug("输入参数: {}", JSON.toJSONString(inputData));

            // 创建模型实例
            LAG_3 model = new LAG_3(inputData);

            // 执行计算
            model.predict();

            log.info("LAG_3模型计算完成");
            
            // 获取标准化输出对象（与output文件格式一致）
            tech.waterism.model.dto.ModelOutputSimple output = model.getLastOutput();
            log.debug("计算结果: {}", JSON.toJSONString(output));

            // 返回ModelOutputSimple对象（与output文件格式一致）
            return ResponseEntity.ok(output);

        } catch (IllegalArgumentException e) {
            log.error("LAG_3模型参数错误: {}", e.getMessage());
            return ResponseEntity.badRequest()
                    .body(Map.of(
                            "error", "参数错误",
                            "message", e.getMessage()
                    ));

        } catch (Exception e) {
            log.error("LAG_3模型计算失败", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of(
                            "error", "计算失败",
                            "message", e.getMessage()
                    ));
        }
    }

    @PostMapping("/calculate/async")
    @Operation(
            summary = "LAG_3模型异步计算",
            description = """
                    提交LAG_3模型异步计算任务，立即返回任务ID。
                    
                    **适用场景：** 大规模计算（>500时段）、批量计算
                    
                    **工作流程：**
                    1. 提交计算任务，立即返回任务ID
                    2. 使用任务ID轮询查询计算状态和结果
                    3. 计算完成后可获取结果
                    
                    ## 返回结果
                    - `taskId`: 任务ID（用于后续查询）
                    - `status`: 任务状态（SUBMITTED）
                    - `queryUrl`: 查询接口URL
                    """
    )
    public ResponseEntity<?> calculateAsync(@RequestBody Map<String, Object> inputData) {
        try {
            log.info("收到LAG_3模型异步计算请求");

            // 生成任务ID
            String taskId = UUID.randomUUID().toString();

            // 提交异步计算任务
            CompletableFuture<tech.waterism.model.dto.ModelOutputSimple> future = calculationService.calculateLAG3Async(inputData);

            // 缓存任务
            taskCache.put(taskId, future, "LAG_3");

            log.info("LAG_3异步计算任务已提交 - taskId: {}", taskId);

            return ResponseEntity.accepted()
                    .body(Map.of(
                            "taskId", taskId,
                            "status", "SUBMITTED",
                            "message", "计算任务已提交，请使用taskId查询结果",
                            "queryUrl", "/api/model/lag/task/" + taskId,
                            "modelName", "LAG_3"
                    ));

        } catch (Exception e) {
            log.error("提交LAG_3异步任务失败", e);
            return ResponseEntity.internalServerError()
                    .body(Map.of(
                            "error", "提交失败",
                            "message", e.getMessage()
                    ));
        }
    }

    @GetMapping("/task/{taskId}")
    @Operation(
            summary = "查询异步计算任务状态",
            description = """
                    根据任务ID查询LAG_3模型异步计算任务的状态和结果。
                    
                    ## 任务状态
                    - `RUNNING`: 计算进行中
                    - `COMPLETED`: 计算完成，返回结果
                    - `FAILED`: 计算失败，返回错误信息
                    - `NOT_FOUND`: 任务不存在或已过期
                    
                    **注意：** 任务结果保留1年，过期后自动清理
                    """
    )
    public ResponseEntity<?> getTaskStatus(@PathVariable String taskId) {
        log.debug("查询任务状态 - taskId: {}", taskId);

        ModelTaskCache.TaskInfo taskInfo = taskCache.getTaskInfo(taskId);

        if (taskInfo == null) {
            return ResponseEntity.status(404)
                    .body(Map.of(
                            "taskId", taskId,
                            "status", "NOT_FOUND",
                            "message", "任务不存在或已过期"
                    ));
        }

        CompletableFuture<tech.waterism.model.dto.ModelOutputSimple> future = taskInfo.getFuture();

        if (future.isDone()) {
            try {
                // 获取ModelOutputSimple结果
                tech.waterism.model.dto.ModelOutputSimple output = future.get();
                log.info("任务已完成 - taskId: {}", taskId);
                
                // 直接返回ModelOutputSimple对象（与output文件格式一致）
                return ResponseEntity.ok(output);
                
            } catch (Exception e) {
                return ResponseEntity.ok(Map.of(
                        "taskId", taskId,
                        "status", "FAILED",
                        "modelName", taskInfo.getModelName(),
                        "error", e.getCause() != null ? e.getCause().getMessage() : e.getMessage()
                ));
            }
        } else {
            return ResponseEntity.ok(Map.of(
                    "taskId", taskId,
                    "status", "RUNNING",
                    "modelName", taskInfo.getModelName(),
                    "createTime", taskInfo.getCreateTime().toString(),
                    "message", "计算进行中，请稍后查询"
                    ));
        }
    }

    @GetMapping("/info")
    @Operation(
            summary = "获取LAG_3模型信息",
            description = "返回LAG_3模型的基本信息、参数说明等"
    )
    public ResponseEntity<?> getModelInfo() {
        return ResponseEntity.ok(Map.of(
                "modelName", "LAG_3",
                "modelFullName", "三水源滞后演算模型",
                "description", "三水源河道汇流计算模型（地表径流+壤中流+地下水）",
                "version", "2.0.0",
                "parameters", Map.of(
                        "LAG", "滞时 (时段) - 范围: 1-10",
                        "KK", "河道演算系数 - 范围: 0.3-0.8",
                        "CS", "河道消退系数 - 范围: 0-1",
                        "CI", "壤中流消退系数 - 范围: 0-1",
                        "CG", "地下水消退系数 - 范围: 0-1",
                        "X", "马斯京根权重系数 - 范围: 0-0.5",
                        "MP", "河段数量",
                        "F", "流域面积 (km²)"
                ),
                "algorithm", "马斯京根法 + 三水源滞后演算",
                "sources", List.of("地表径流(RS)", "壤中流(RI)", "地下水(RG)")
        ));
    }
}

